import configparser
import sys
import traceback
import os

sys.path.append("/netboxSyncZabbix")
from loguru import logger
from api import netbox_api, zabbix_api62, weixin_webhook

logger.add("/var/log/Task/zabbix_sync_service/zabbix_sync_service.log", rotation="00:00", backtrace=True, diagnose=True,
           level="DEBUG")

# 获取配置文件
dir_name = os.path.dirname(os.path.dirname(__file__))
ini_path = f"{dir_name}/config.ini"

config = configparser.ConfigParser()
config.read(ini_path)

# 关联脚本变量
# 通用变量
limit = config.get("netbox", "limit")
verify = config.getboolean("netbox", "verify")

# 正式环境变量
netbox_url = config.get("netbox", "url")
netbox_token = config.get("netbox", "token")
zabbix_server_url = config.get("zabbix", "url")
zabbix_user = config.get("zabbix", "user")
zabbix_passwd = config.get("zabbix", "passwd")
webhook_Zabbix_Service = config.get("global", "webhook_Zabbix_Service")

# 测试环境变量
# netbox_url = config.get("netbox", "test_url")
# netbox_token = config.get("netbox", "test_token")
# zabbix_server_url = config.get("zabbix_test", "url")
# zabbix_user = config.get("zabbix_test", "user")
# zabbix_passwd = config.get("zabbix_test", "passwd")

# 注： 修改 SLO 和 Type 时需要修改下面修改 tags 的判断条件
SLO = "Network"
Type = "SubService"
first_name = "Network"
second_name = ["Backbone", "Dhcp", "Dns", "Lan", "Wired", "Wireless"]
third_name = ["MainDevice", "Wan"]


# tags = [{"SLO": "Network", "Type": "SubService"}]

# 获取netbox中所有站点的站点代码及站点id

def get_site_slug_id(netbox_url, netbox_token):
    site_dict = {}
    site_list = []
    try:
        site_info = netbox_api.netbox_get_site(netbox_token, netbox_url, verify=False)
        for site in site_info["results"]:
            if (site.get("tenant") and site.get("tenant").get("name") == "Netops") and (
                    site.get("status").get("value") == "active"):
                site_dict[str(site["id"])] = site["slug"]
                # site_dict = {"id": site["id"], "slug": site["slug"]}
                # site_list.append(site_dict)
        logger.info(f"获取netbox站点代码及站点id成功")
    except Exception:
        logger.error(f"获取netbox站点代码及站点id失败，报错信息:{traceback.format_exc()}")
    print(site_list)
    return site_dict


# get_site_slug_id(netbox_url, netbox_token)

def get_zabbix_slug_id(zabbix_server_url, zabbix_token):
    Network_Avaliability_id = ""
    Network_Avaliability_Deprecated_id = ""
    network_services_list = []
    site_id_list = []
    site_id_serviceid = {}
    try:
        # zabbix_all_service = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url, serviceids=16)
        zabbix_all_service = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url)
        for service in zabbix_all_service["result"]:
            if service["name"] == "Network-Avaliability":
                Network_Avaliability_id = service["serviceid"]
            elif service["name"] == "Network-Avaliability-Deprecated":
                Network_Avaliability_Deprecated_id = service["serviceid"]
        if Network_Avaliability_id:
            # tags = [{"tag": "site_id", "value": str(site_list["id"])}]
            # name = site_list["slug"] + "Network"
            network_services = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url,
                                                               parentids=Network_Avaliability_id)
            for i in network_services["result"]:
                site_id = i["description"].split("\n")[0].strip().split("=")[-1].strip()
                if site_id:
                    site_id_serviceid[site_id] = i["serviceid"]
                    site_id_list.append(site_id)
            print(network_services)
            network_services_list = network_services["result"]
        zabbix_dict = {"network_services_list": network_services_list,
                       "Network_Avaliability_id": Network_Avaliability_id,
                       "Network_Avaliability_Deprecated_id": Network_Avaliability_Deprecated_id,
                       "site_id_serviceid": site_id_serviceid}
        logger.info(f"获取zabbix的service信息成功")
        return {"success": True, "resp": zabbix_dict}
    except Exception:
        logger.error(f"获取zabbix的service信息失败，报错信息：{traceback.format_exc()}")
        return {"success": False, "resp": "获取zabbix的service信息失败"}


if __name__ == '__main__':
    create_success = []
    create_fail = []
    update_success = []
    update_fail = []
    delete_success = []
    delete_fail = []
    tags_update_success = []
    tags_update_fail = []

    # 获取zabbix的token
    zabbix_token = zabbix_api62.zabbix_get_token(zabbix_user, zabbix_passwd, zabbix_server_url, verify)
    # 先进行组同步
    netbox_site_dict = get_site_slug_id(netbox_url, netbox_token)
    if not netbox_site_dict:
        logger.error(f"查询netbox的站点信息失败")
    zabbix_resp = get_zabbix_slug_id(zabbix_server_url, zabbix_token)
    if not zabbix_resp["success"]:
        logger.error(f"查询zabbix的service信息失败")
    zabbix_dict = zabbix_resp["resp"]
    # 正在启用的组id
    Network_Avaliability_id = zabbix_dict["Network_Avaliability_id"]
    # 弃用组
    Network_Avaliability_Deprecated_id = zabbix_dict['Network_Avaliability_Deprecated_id']
    # 第一层的service
    zabbix_service_list = zabbix_dict['network_services_list']
    netbox_site_id_list = list(netbox_site_dict.keys())
    # {site_id: serviceid}
    zabbix_site_id_serviceid = zabbix_dict["site_id_serviceid"]
    zabbix_site_id_list = list(zabbix_site_id_serviceid.keys())
    # netbox 中有但是zabbix中没有的，zabbix应该创建
    only_netbox_have = list(set(netbox_site_id_list).difference(set(zabbix_site_id_list)))  # [1, 2, 3]
    # netbox 中没有但是zabbix中有的，zabbix应该删除
    only_zabbix_have = list(set(zabbix_site_id_list).difference(set(netbox_site_id_list)))
    # netbox中和zabbix中都有的， 应检查zabbix中与netbox中是否一致，不一致则修改
    all_have = list(set(netbox_site_id_list).intersection(set(zabbix_site_id_list)))
    # """
    if only_netbox_have:
        # zabbix 创建
        for site_id in only_netbox_have:
            site_slug = netbox_site_dict[site_id]
            try:
                first_service_name = f"{site_slug}-{first_name}"
                description = f"site_id={site_id}"
                first_service_tags = [{"tag": "SLO", "value": SLO}]
                zabbix_first_created = zabbix_api62.zabbix_create_service(zabbix_token, zabbix_server_url,
                                                                          first_service_name, first_service_tags,
                                                                          description,
                                                                          parents=[{"serviceid": int(
                                                                              zabbix_dict[
                                                                                  "Network_Avaliability_id"])}, ],
                                                                          algorithm=2, propagation_rule=2)
                print(f"创建第一层:{zabbix_first_created['result']['serviceids']}")
                for second_end_name in second_name:
                    second_service_name = f"{site_slug}-{second_end_name}"
                    second_service_tags = [{"tag": "SLO", "value": SLO}, {"tag": "Type", "value": Type}]
                    if second_end_name == "Backbone":
                        zabbix_second_created = zabbix_api62.zabbix_create_service(zabbix_token, zabbix_server_url,
                                                                                   second_service_name,
                                                                                   second_service_tags,
                                                                                   parents=[{"serviceid": int(
                                                                                       zabbix_first_created["result"][
                                                                                           "serviceids"][0])}, ],
                                                                                   algorithm=2, propagation_rule=2)
                        for third_end_name in third_name:
                            third_service_name = f"{site_slug}-{third_end_name}"
                            third_service_tags = [{"tag": "SLO", "value": SLO}, {"tag": "Type", "value": Type}]
                            zabbix_third_created = zabbix_api62.zabbix_create_service(zabbix_token, zabbix_server_url,
                                                                                      third_service_name,
                                                                                      third_service_tags,
                                                                                      parents=[{"serviceid": int(
                                                                                          zabbix_second_created[
                                                                                              "result"][
                                                                                              "serviceids"][0])}, ],
                                                                                      algorithm=2)
                            print(f"创建第三层:{zabbix_third_created['result']['serviceids']}")
                    else:
                        zabbix_second_created = zabbix_api62.zabbix_create_service(zabbix_token, zabbix_server_url,
                                                                                   second_service_name,
                                                                                   second_service_tags,
                                                                                   parents=[{"serviceid": int(
                                                                                       zabbix_first_created["result"][
                                                                                           "serviceids"][0])}, ],
                                                                                   algorithm=2)
                    print(f"创建第二层:{zabbix_second_created['result']['serviceids']} \n")
                create_success.append(f"{site_slug}-{first_name}")
            except Exception:
                logger.error(f"创建service失败，站点代码：{site_slug}，站点id：{site_id}，报错信息：{traceback.format_exc()}")
                create_fail.append(f"{site_slug}-{first_name}")
                continue
    if only_zabbix_have:
        # zabbix 删除
        for zabbix_site_id in only_zabbix_have:
            serviceid = zabbix_site_id_serviceid[zabbix_site_id]
            service_info = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url, serviceids=serviceid)
            try:
                zabbix_updated = zabbix_api62.zabbix_update_service(zabbix_token, zabbix_server_url, serviceid,
                                                                    parents=[
                                                                        {
                                                                            "serviceid": Network_Avaliability_Deprecated_id}])
                logger.info(f"站点id:{zabbix_service_list},serviceid:{serviceid},已弃用")
                delete_success.append(service_info["result"][0]["name"])
            except Exception:
                logger.error(
                    f"zabbix删除service失败，站点代码：{zabbix_site_id}，serviceid:{serviceid},报错信息：{traceback.format_exc()}")
                delete_fail.append(service_info["result"][0]["name"])
                continue

    if all_have:
        for site_id in all_have:
            # zabbix 中的servieid
            serviceid = zabbix_site_id_serviceid[site_id]
            # netbox 中的site_code
            site_slug = netbox_site_dict[site_id]
            try:
                # 获取serviceid的信息
                get_service = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url, serviceids=serviceid)
                service_info = get_service["result"][0]
                if service_info["name"].split("-")[0].strip() != site_slug:
                    # 修改这个service的name
                    zabbix_updated = zabbix_api62.zabbix_update_service(zabbix_token, zabbix_server_url, serviceid,
                                                                        name=f"{site_slug}-{first_name}")
                    # 获取以这个service为父级的service
                    get_childids_service = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url,
                                                                           parentids=serviceid)
                    childids_service = get_childids_service["result"]
                    for childid in childids_service:
                        childid_serviceid = childid["serviceid"]
                        childid_name = childid["name"]
                        end_name = childid_name.split("-")[-1].strip()
                        zabbix_updated = zabbix_api62.zabbix_update_service(zabbix_token, zabbix_server_url,
                                                                            childid_serviceid,
                                                                            name=f"{site_slug}-{end_name}")
                        if "Backbone" in childid_name:
                            backbone_childids_service = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url,
                                                                                        parentids=childid_serviceid)
                            backbone_childids_service = backbone_childids_service["result"]
                            for backbone_childid in backbone_childids_service:
                                backbone_childid_serviceid = backbone_childid["serviceid"]
                                childid_name = backbone_childid["name"]
                                backbone_end_name = childid_name.split("-")[-1].strip()
                                backbone_zabbix_updated = zabbix_api62.zabbix_update_service(zabbix_token,
                                                                                             zabbix_server_url,
                                                                                             backbone_childid_serviceid,
                                                                                             name=f"{site_slug}-{backbone_end_name}")
                                print(backbone_zabbix_updated)
                    update_success.append(f"{site_slug}-{first_name}")
            except Exception:
                logger.error(
                    f"更新service失败，站点代码：{site_slug}, 站点id：{site_id}, 报错信息：{traceback.format_exc()}")
                update_fail.append(f"{site_slug}-{first_name}")
                continue
    # """
    if Type != "SubService" or SLO != "Network":
        # 第一层 service
        for first_service in zabbix_service_list:
            try:
                first_serviceid = first_service["serviceid"]
                first_service_name = first_service["name"]
                first_child_service_get = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url,
                                                                          parentids=first_serviceid)
                if SLO != "Network test":
                    # 第一层也修改
                    first_tags = [{"tag": "SLO", "value": SLO}]
                    first_service_update = zabbix_api62.zabbix_update_service(zabbix_token, zabbix_server_url,
                                                                              first_serviceid, tags=first_tags)
                    print(f"更新{first_service_name}的tag")
                # 修改第二、三层
                first_child_service = first_child_service_get["result"]
                for second_service in first_child_service:
                    second_serviceid = second_service["serviceid"]
                    second_service_name = second_service["name"]
                    tags = [{"tag": "SLO", "value": SLO}, {"tag": "Type", "value": Type}]
                    second_service_update = zabbix_api62.zabbix_update_service(zabbix_token, zabbix_server_url,
                                                                               second_serviceid, tags=tags)
                    print(f"更新{first_service_name}中{second_service_name}的tag")
                    if "Backbone" in second_service_name:
                        third_services_get = zabbix_api62.zabbix_get_service(zabbix_token, zabbix_server_url,
                                                                             parentids=second_serviceid)
                        third_services = third_services_get["result"]
                        for third_service in third_services:
                            third_service_name = third_service["name"]
                            third_serviceid = third_service["serviceid"]
                            tags = [{"tag": "SLO", "value": SLO}, {"tag": "Type", "value": Type}]
                            third_service_update = zabbix_api62.zabbix_update_service(zabbix_token, zabbix_server_url,
                                                                                      third_serviceid, tags=tags)
                            print(f"更新{first_service_name}中{second_service_name}中{third_service_name}的tag")
                tags_update_success.append(first_service_name)
            except Exception:
                logger.error(f"更新tag失败,service名称：{first_service_name},报错信息：{traceback.format_exc()}")
                tags_update_fail.append(first_service_name)
                continue

    content = f"## Zabbix同步Service报告(Task): \n"
    if netbox_site_dict and zabbix_resp[
        "success"] and not create_success and not create_fail and not update_success and not update_fail and not \
            delete_success and not delete_fail and not tags_update_success and not tags_update_fail:
        content += f">** 本次无更新，所有Service与Netbox的Site信息一致 **"
    if not netbox_site_dict:
        content += f">**Netbox获取站点信息失败，请检查**\n"
    if not zabbix_resp["success"]:
        content += f">**Zabbix获取Service信息失败，请检查**\n"
    if create_success or create_fail:
        content += ">**Service 创建报告:**\n"
        if create_success:
            content += f"Service 创建成功{len(create_success)}条\n" \
                       f"{create_success}\n"
        if create_fail:
            content += f"Service 创建失败{len(create_fail)}条\n" \
                       f"{create_fail}\n"
    if update_success or update_fail:
        content += ">**Service 更新报告:**\n"
        if update_success:
            content += f"Service 更新成功{len(update_success)}条\n" \
                       f"{update_success}\n"
        if update_fail:
            content += f"Service 更新失败{len(update_success)}条\n" \
                       f"{update_success}\n"
    if delete_success or delete_fail:
        content += ">**Service 删除(弃用)报告:**\n"
        if delete_success:
            content += f"Service 删除(弃用)成功{len(delete_success)}条\n" \
                       f"{delete_success}\n"
        if delete_fail:
            content += f"Service 删除(弃用)失败{len(delete_fail)}条\n" \
                       f"{delete_fail}\n"
    if tags_update_success or tags_update_fail:
        content += ">**Service tags 更新报告:**\n"
        if tags_update_success:
            content += f"Service tags 更新成功{len(tags_update_success)}条\n" \
                       f"{tags_update_success}\n"
        if tags_update_fail:
            content += f"Service tags 更新失败{len(tags_update_fail)}条\n" \
                       f"{tags_update_fail}\n"
    logger.info("Zabbix同步Service报告(Task)：\n", content)
    response = weixin_webhook.send_to_webhook(webhook_Zabbix_Service, content)
    logger.info(response)
